
package com.bear.cmcc.NetTestHTTP.util;

import com.bear.cmcc.NetTestHTTP.NetworkTestApp;
import com.bear.cmcc.NetTestHTTP.constant.FtpConstant;
import com.bear.cmcc.NetTestHTTP.constant.MyCommonConstant;
import com.bear.cmcc.NetTestHTTP.service.LocalUpdateVillageDBService;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import java.util.ArrayList;

/**
 * FTP相关的工具类。
 * 
 * @author suchangjun
 */
public class FtpUtil {

    private static final String TAG = "FtpUtil";

    /**
     * 把日志上传到福建ftp服务器。
     * 
     * @param context
     */
    public static boolean upLoadAllFileToFjFTPTest(Context context) {
        boolean success = false;
        if (context == null) {
            return false;
        }
        FTPClient ftp = null;
        try {
            if (MyCommonUtil.isNetworkAviable(context)) {
                ftp = ftpInitial(FtpConstant.ComFtpFjConfig.hostFJ, null,
                        FtpConstant.ComFtpFjConfig.userUploadFJ,
                        FtpConstant.ComFtpFjConfig.passUploadFJ);
        
                OutputStream  out=ftp.storeFileStream("scjtest.zip");
                int bb=ftp.getReply();
                if(out!=null)
                {
                    int kk=ftp.getReply();
                }
                
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, " upLoadAllFileByComFTP -->Exception: " + e.getMessage());
        } finally {
            ftpDestroy(ftp);
        }
        return success;

    }
    
    /**
     * 把日志上传到福建ftp服务器。
     * 
     * @param context
     */
    public static boolean upLoadAllFileToFjFTP(Context context) {
        boolean success = false;
        if (context == null) {
            return false;
        }
        FTPClient ftp = null;
        try {
            if (MyCommonUtil.isNetworkAviable(context)) {
                ftp = ftpInitial(FtpConstant.ComFtpFjConfig.hostFJ, null,
                        FtpConstant.ComFtpFjConfig.userUploadFJ,
                        FtpConstant.ComFtpFjConfig.passUploadFJ);
                File file = new File(context.getFilesDir() + "/"
                        + FtpConstant.FtpFileNames.logsaveaddressfj);
                if (!file.exists()) {
                    return false;
                }
                success = uploadLogToFtpService(ftp, file);
            }
        } catch (Exception e) {
            Log.d(TAG, " upLoadAllFileByComFTP -->Exception: " + e.getMessage());
        } finally {
            ftpDestroy(ftp);
        }
        return success;

    }

//    /**
//     * 把日志上传到通用ftp服务器。
//     * 
//     * @param context
//     */
//    public static boolean upLoadAllFileToComFTP(Context context) {
//        boolean success = false;
//        if (context == null) {
//            return false;
//        }
//        FTPClient ftp = null;
//        try {
//            if (MyCommonUtil.isNetworkAviable(context)) {
//                ftp = ftpInitial(FtpConstant.ComFtpConfig.host, FtpConstant.ComFtpConfig.hostport,
//                        FtpConstant.ComFtpConfig.userUpload, FtpConstant.ComFtpConfig.passUpload);
//                File file = new File(context.getFilesDir() + "/"
//                        + FtpConstant.FtpFileNames.logsaveaddress);
//                if (!file.exists()) {
//                    return false;
//                }
//                success = uploadLogToFtpService(ftp, file);
//            }
//        } catch (Exception e) {
//            Log.d(TAG, " upLoadAllFileByComFTP -->Exception: " + e.getMessage());
//        } finally {
//            ftpDestroy(ftp);
//        }
//        return success;
//
//    }

    /**
     * 通用FTP文件下载，FTP现在服务器分为三个部分，一个是通用的，一个是福建的，一个是北京的。
     * 
     * @param context
     * @param localPath 要下载文件保存文件名。
     * @param remotePath ftp服务器上面文件路径。
     */
    public static boolean downloadFileByComFTP(Context context, String localPath, String remotePath) {
        return downloadFileByComFTP(context, localPath, remotePath, false, null);
    }
    


    /**
     * 通用FTP文件下载，FTP现在服务器分为三个部分，一个是通用的，一个是福建的，一个是北京的。
     * 
     * @param context
     * @param localPath 要下载文件保存文件名。
     * @param remotePath ftp服务器上面文件路径。
     * @param isFileCanWrite 下载 的文件是否可读写
     */
    public static boolean downloadFileByComFTP(Context context, String localPath,
            String remotePath, boolean isFileCanWrite) {
        return downloadFileByComFTP(context, localPath, remotePath, isFileCanWrite, null);
    }

    /**
     * 自动获取ftp句柄，如果不能获取集团的，那么就连接福建的服务器。
     * @return
     */
    public static FTPClient getCommonFtp() {
        FTPClient ftp = ftpInitial(FtpConstant.ComFtpConfig.host,
                FtpConstant.ComFtpConfig.hostport, FtpConstant.ComFtpConfig.userDownload,
                FtpConstant.ComFtpConfig.passDownload);
        if (ftp == null) {
            Log.i(TAG, "不能连接集团服务器，连接福建服务器");
            ftp = ftpInitial(FtpConstant.ComFtpFjConfig.hostFJ, null,
                    FtpConstant.ComFtpFjConfig.userDownloadFJ,
                    FtpConstant.ComFtpFjConfig.passDownloadFJ);
        }
        return ftp;
    }
    
    /**
     * 通用FTP文件下载，FTP现在服务器分为三个部分，一个是通用的，一个是福建的，一个是北京的。
     * 
     * @param context
     * @param localPath 要下载文件保存文件名。
     * @param remotePath ftp服务器上面文件路径。
     * @param isFileCanWrite 下载的文件是否可读写
     * @param villageService 下载小区信息文件的服务对象
     */
    public static boolean downloadFileByComFTP(Context context, String localPath,
            String remotePath, boolean isFileCanWrite, LocalUpdateVillageDBService villageService) {
        
        return downloadFileByComFTP(context,localPath,remotePath,isFileCanWrite,villageService,false);
    }

    /**
     * 通用FTP文件下载，FTP现在服务器分为三个部分，一个是通用的，一个是福建的，一个是北京的。
     * 
     * @param context
     * @param localPath 要下载文件保存文件名。
     * @param remotePath ftp服务器上面文件路径。
     * @param isFileCanWrite 下载的文件是否可读写
     * @param villageService 下载小区信息文件的服务对象
     */
    public static boolean downloadFileByComFTP(Context context, String localPath,
            String remotePath, boolean isFileCanWrite, LocalUpdateVillageDBService villageService,boolean isChangeTime) {
        boolean success = false;
        if (context == null || localPath == null || remotePath == null) {
            return false;
        }

        FTPClient ftp = null;
        try {
            if (MyCommonUtil.isNetworkAviable(context)) {
                ftp = getCommonFtp();
                
                if(isChangeTime&&ftp!=null)
                {
                    ftp.setConnectTimeout(FtpConstant.FTP_CONNECT_TIME_OUT_20);
                }

                File file = new File(context.getFilesDir() + "/" + localPath);
                if (file.exists()) {
                    file.delete();
                }
                success = downloadFile(ftp, context.getFilesDir() + "/" + localPath, remotePath,
                        context, isFileCanWrite, villageService);
            }
        } catch (Exception e) {
            Log.d(TAG, "  -->Exception: " + e.getMessage());
        } finally {
            ftpDestroy(ftp);
        }
        return success;

    }

    /**
     * 通用FTP文件下载，FTP现在服务器分为三个部分，一个是通用的，一个是福建的，一个是北京的。 注意 本地保存的文件名和远程文件名称一样。
     * 
     * @param context
     * @param remotePaths ftp服务器上面文件路径。
     */
    public static boolean downloadFileByComFTP(Context context, String[] remotePaths) {
        boolean success = false;
        if (context == null || remotePaths == null || remotePaths.length <= 0) {
            return success;
        }

        FTPClient ftp = null;
        try {
            if (MyCommonUtil.isNetworkAviable(context)) {
                ftp = getCommonFtp();
                boolean temp = true;
                for (String remotePath : remotePaths) {
                    if (remotePath != null) {
                        File file = new File(context.getFilesDir() + "/" + remotePath);
                        if (file.exists()) {
                            file.delete();
                        }
                        temp = downloadFile(ftp, context.getFilesDir() + "/" + remotePath,
                                remotePath, context, false, null);
                    }
                    if (!temp) {
                        break;
                    }

                }
                success = temp;

            }
        } catch (Exception e) {
            Log.d(TAG, "  -->Exception: " + e.getMessage());
        } finally {
            ftpDestroy(ftp);
        }
        return success;
    }

    /**
     * 福建FTP文件下载，FTP现在服务器分为三个部分，一个是通用的，一个是福建的，一个是北京的。 注意 本地保存的文件名和远程文件名称一样。
     * 
     * @param context
     * @param remotePaths ftp服务器上面文件路径。
     */
    public static boolean downloadFileByFjFTP(Context context, String[] remotePaths) {
        
        return downloadFileByFjFTP(context,remotePaths,false);
    }
    
    
    /**
     * 福建FTP文件下载，FTP现在服务器分为三个部分，一个是通用的，一个是福建的，一个是北京的。 注意 本地保存的文件名和远程文件名称一样。
     * 
     * @param context
     * @param remotePaths ftp服务器上面文件路径。
     */
    public static boolean downloadFileByFjFTP(Context context, String[] remotePaths,boolean isChangeTime) {
        boolean success = false;
        if (context == null || remotePaths == null || remotePaths.length <= 0) {
            return success;
        }

        FTPClient ftp = null;
        try {
            if (MyCommonUtil.isNetworkAviable(context)) {
                ftp = ftpInitial(FtpConstant.ComFtpFjConfig.hostFJ, null,
                        FtpConstant.ComFtpFjConfig.userDownloadFJ,
                        FtpConstant.ComFtpFjConfig.passDownloadFJ);
                
                if(ftp!=null&&isChangeTime)
                {
                    ftp.setConnectTimeout(FtpConstant.FTP_CONNECT_TIME_OUT_20);
                    
                }
                
                boolean temp = true;
                File fj = new File(context.getFilesDir() + FtpConstant.FJ_FLOADER);
                if (!fj.exists()) {
                    temp = fj.mkdir();
                }
                if (!temp) {
                    return temp;
                }

                for (String remotePath : remotePaths) {
                    if (remotePath != null) {
                        File file = new File(remotePath);
                        if (file.exists()) {
                            file.delete();
                        }
                        temp = downloadFile(ftp, context.getFilesDir() + FtpConstant.FJ_FLOADER
                                + remotePath, remotePath, context, false, null);
                    }
                    if (!temp) {
                        break;
                    }

                }
                success = temp;

            }
        } catch (Exception e) {
            Log.d(TAG, "  -->Exception: " + e.getMessage());
        } finally {
            ftpDestroy(ftp);
        }
        return success;
    }

    /**
     * 断开ftp并销毁。
     * 
     * @param ftp
     */
    public static void ftpDestroy(FTPClient ftp) {
        try {
            if (ftp != null && ftp.isConnected()) {
                ftp.disconnect();
                Log.d(TAG, " -->ftpDestroy");
            }
            ftp = null;
        } catch (IOException e) {
            Log.d(TAG, " -->ftpDestroy IOException: " + e.getMessage());
        } catch (Exception e) {
            Log.d(TAG, " -->ftpDestroy Exception: " + e.getMessage());
        }
    }

    /**
     * 初始化FTP客户端，注意为安全考虑，上传和下载的密码不一致。
     * 
     * @param host 要连接FTP的服务器地址。
     * @param hostport 要连接FTP 服务器端口。
     * @param user 用户名。
     * @param pass 密码
     * @return FTPClient 客户端。
     */
    public static FTPClient ftpInitial(String host, String hostport, String user, String pass) {
        FTPClient ftp = new FTPClient();
        boolean success = false;
        int reply = -1;
        ftp.setConnectTimeout(FtpConstant.FTP_CONNECT_TIME_OUT);
        ftp.setDataTimeout(FtpConstant.FTP_DATA_TIME_OUT);
        ftp.setDefaultTimeout(FtpConstant.FTP_Default_TIME_OUT);        
        try {
            if (hostport == null || hostport.equals("")) {
                ftp.connect(host);
            } else {
                ftp.connect(host, Integer.parseInt(hostport));
            }
            //模式要放到已经连接后，设置才能生效
            ftp.enterLocalPassiveMode(); 
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                Log.d(TAG, " -->ftpInitial fail. ReplyCode: " + ftp.getReplyString());
                return null;
            }

            success = ftp.login(user, pass);

            success = ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftp.setControlEncoding(FtpConstant.FTP_CHARSET);

        } catch (SocketException e) {
            Log.d(TAG, " -->ftpInitial SocketException: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, " -->ftpInitial IOException: " + e.getMessage());
        } catch (Exception e) {
            Log.d(TAG, " -->ftpInitial Exception: " + e.getMessage());
        } finally {
            if (!success) {
                if (ftp != null) {
                    try {
                        ftp.disconnect();
                    } catch (IOException e) {
                        Log.d(TAG, " -->login fail!");
                    }
                }
                ftp = null;
                Log.d(TAG, " -->login fail!");
            } else {
                Log.d(TAG, " -->login successfully");
            }
        }
        return ftp;
    }

    /**
     * 从FTP服务器器下载文件。
     * 
     * @param ftp ftp客户端句柄。
     * @param localPath 本地保存文件路径。
     * @param remotePath ftp服务器上面文件地址。
     * @param context
     * @param isFileCanWrite 下载的文件是否要设置成可写。
     * @return 成功与否。
     */
    private static boolean downloadFile(FTPClient ftp, String localPath, String remotePath,
            Context context, boolean isFileCanWrite, LocalUpdateVillageDBService villageService) {
        Log.d(TAG, "NetTestService downloadFile " + remotePath);
        float totalSize = 0;// 文件总长度
        int currentSize = 0;// 当前已下载文件的大小
        int currentPer = 0;// 当前的下载进度
        int reply = -1;
        int cache = FtpConstant.FTP_DOWN_FILE_CACHE_SIZE;
        boolean success = false;
        String fileName = null;
        FileOutputStream fos = null;
        BufferedOutputStream outStream = null;
        InputStream inputStream = null;
        try {
            File file = new File(localPath);
            if (file.exists()) {
                return true;
            }
            fileName = file.getName();
            if (isFileCanWrite) {
                String endPath = "/files/";
                int endIndex = localPath.indexOf(endPath);
                if (endIndex != -1) {
                    localPath = localPath
                            .substring(endIndex + endPath.length(), localPath.length());
                }
                // 传入的路径必须是files/目录下的文件
                fos = context.openFileOutput(localPath, Context.MODE_WORLD_READABLE);
            } else {
                fos = new FileOutputStream(file);
            }

            outStream = new BufferedOutputStream(fos);
            inputStream = ftp.retrieveFileStream(remotePath);
            // 取totalSize长度 ,此取不到,待下载帐号有权限时，用此方法取文件的总长度
            totalSize = 8931965;// ftp.listFiles(remotePath)[0].getSize();
            if (inputStream != null) {
                byte[] b = new byte[cache];
                int j = 0;
                j = inputStream.read(b, 0, cache);
                while (j > 0) {
                    fos.write(b, 0, j);
                    j = inputStream.read(b, 0, cache);

                    currentSize += j;
                    // 只有当下载小区信息文件csv的服务时，才调用
                    if (villageService != null && totalSize > 0) {
                        if (NetworkTestApp.isStop_celldb) {
                            // 取消更新
                            return false;
                        }

                        int tmp = (int) (currentSize * 100 / totalSize);
                        // 为了防止频繁的通知导致应用吃紧，百分比增加2才通知一次
                        if (currentPer == 0 || tmp - 2 > currentPer) {
                            currentPer += 2;
                            if (currentPer > 100) {
                                currentPer = 100;
                            }
                            villageService
                                    .sendFileDownBroad(
                                            MyCommonConstant.PrivateActionName.SERVICE_DOWN_VILLAGE_TYPE_CSV,
                                            0, currentPer);
                        }
                    }

                }
                if (villageService != null) {
                    // 下载小区信息csv完成
                    villageService.sendFileDownBroad(
                            MyCommonConstant.PrivateActionName.SERVICE_DOWN_VILLAGE_TYPE_CSV, 1,
                            100);
                }
            }

            outStream.flush();
            fos.flush();
            success = ftp.completePendingCommand();

            reply = ftp.getReplyCode();
            if (reply == FtpConstant.FTP_DOWN_FILE_SUCCESS) {
                success = true;
                Log.d(TAG, "downloadFile " + fileName + " successfully.");
            } else {
                success = false;
                Log.d(TAG,
                        "downloadFile " + fileName + " fail. Reply Code: " + ftp.getReplyString());
            }
        } catch (SocketException e) {
            e.printStackTrace();
            Log.d(TAG, "downloadFile SocketException " + e.getMessage());
            if (villageService != null) {
                // 下载csv错误
                villageService.sendFileDownBroad(
                        MyCommonConstant.PrivateActionName.SERVICE_DOWN_VILLAGE_TYPE_CSV, -1, 0);
            }
        } catch (IOException e) {
            e.printStackTrace();
            Log.d(TAG, "downloadFile IOException " + e.getMessage());
            if (villageService != null) {
                // 下载csv错误
                villageService.sendFileDownBroad(
                        MyCommonConstant.PrivateActionName.SERVICE_DOWN_VILLAGE_TYPE_CSV, -1, 0);
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, "downloadFile Exception " + e.getMessage());
            if (villageService != null) {
                // 下载csv错误
                villageService.sendFileDownBroad(
                        MyCommonConstant.PrivateActionName.SERVICE_DOWN_VILLAGE_TYPE_CSV, -1, 0);
            }
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                }
                if (outStream != null) {
                    outStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                Log.d(TAG, "downloadFile finally close IOException: " + e.getMessage());
            }
            // 如果文件传输失败，那么就把空文件给删除。
            try {
                if (!success) {
                    File file = new File(localPath);
                    if (file.exists()) {
                        file.delete();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return success;
    }

    /**
     * 上传日志文件到服务器中。
     * 
     * @param ftp ftp句柄。
     * @param file 可以是文件夹或者文件，如果是文件夹那么就直接上传这个文件夹下面的文件。
     * @return 上传成功与否。
     */
    public static boolean uploadLogToFtpService(FTPClient ftp, File file) {
        if (ftp == null || file == null) {
            return false;
        }
        boolean success = false;
        try {
            ArrayList<File> wantUpFile = new ArrayList<File>();
            if (file.isDirectory()) {
                for (File element : file.listFiles()) {
                    if (element != null && (element.length() > 0) && element.isFile()) {
                        wantUpFile.add(element);
                    }
                }
            } else {
                if (file.length() > 0) {
                    wantUpFile.add(file);
                }
            }
            FTPFile[] remoteFile;
            for (File upFile : wantUpFile) {
                try {
                    remoteFile = ftp.listFiles(upFile.getName());
                    if (remoteFile.length > 0) {
                        success = upFile.delete();
                    } else {
                        success = ftpUpload(ftp, upFile);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return success;
    }
    
    /**
     * 把文件上传到服务器中。
     * 
     * @param ftp
     * @param file
     * @return
     */
    private static boolean ftpUpload(FTPClient ftp, File file) {
        boolean success = false;
        if (ftp == null) {
            return false;
        }
        FileInputStream fis = null;
        InputStream inStream = null;
        try {
            int reply = -1;
            if (file.exists()) {
                fis = new FileInputStream(file);
                inStream = new BufferedInputStream(fis);
                ftp.cwd("/");
                success = ftp.storeFile(file.getName(), inStream);
                reply = ftp.getReplyCode();
                if (reply == 226) {
                    Log.d(TAG, "Upload" + file.getName() + "successfully.");
                    success = true;
                    file.delete();

                } else {
                    Log.d(TAG,
                            "Upload" + file.getName() + "Upload fail. Reply Code: "
                                    + ftp.getReplyString());

                    success = false;
                }
            }
        } catch (SocketException e) {
            Log.d(TAG, " -->ftpUpload SocketException: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, " -->ftpUpload IOException: " + e.getMessage());
        } catch (Exception e) {
            Log.d(TAG, " -->ftpUpload Exception: " + e.getMessage());
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
                if (inStream != null) {
                    inStream.close();
                }
            } catch (IOException e) {
                Log.d(TAG, " -->ftpUpload finally close IOException: " + e.getMessage());
            }
        }
        return success;
    }
}
